package com.fjrz.bbxwj.util

import android.os.Handler
import android.os.Looper
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.NetworkUtils
import com.fjrz.bbxwj.app.RZApplication
import com.fjrz.bbxwj.entity.*
import com.module.lemlin.rxhttp.HttpServiceFactory
import okhttp3.*
import org.greenrobot.eventbus.EventBus
import java.lang.Exception
import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue


class HttpWebSocketUtils : WebSocketListener() {

    companion object {
        @Volatile
        private var mHttpWebSocketUtils: HttpWebSocketUtils? = null

        //        private var mWsUrl: String = "wss://mall.jiaquyun.cn/wss"
        private var mWsUrl: String = "ws://47.118.63.80:8282"

        fun instance(): HttpWebSocketUtils? {
            if (mHttpWebSocketUtils == null) synchronized(
                HttpWebSocketUtils::class.java
            ) {
                if (mHttpWebSocketUtils == null)
                    mHttpWebSocketUtils =
                        HttpWebSocketUtils()
            }
            return mHttpWebSocketUtils
        }

        private const val DELAY_MILLIS: Long = 3000 * 10
    }


    private var mWebSocket: WebSocket? = null
    private var mWebSocketListener: WebSocketListener? = null

    private var isLoginSocket: Boolean = false

    init {
        connect()
    }

    private val mHandler = Handler(Looper.myLooper()!!)

    private val mRunnable: Runnable = object : Runnable {
        override fun run() {
            mWebSocket?.send(text = "ping")
            mHandler.postDelayed(this as Runnable, DELAY_MILLIS)
        }
    }

    private val mSendQueue: Queue<String> = ConcurrentLinkedQueue<String>()

    override fun onOpen(webSocket: WebSocket, response: Response) {
        super.onOpen(webSocket, response)
        val open: String = String.format(
            Locale.CHINA, ("onOpen:%s"), ("WebSocket 已开启")
        )
        LogUtils.e(open)

        ping()
        login()
    }

    override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
        super.onFailure(webSocket, t, response)
        this.close()
        mWebSocketListener?.onFailure(webSocket, t, response)
        val open: String = String.format(
            Locale.CHINA, ("onFailure:%s"), ("WebSocket 异常:${t.message}")
        )
        LogUtils.e(open)
    }

    override fun onMessage(webSocket: WebSocket, text: String) {
        super.onMessage(webSocket, text)
        val open: String = String.format(
            Locale.CHINA, ("onMessage:%s"), ("WebSocket 成功:${text}")
        )
        LogUtils.e(open)
        if (text == "pong")
            return
        try {
            val socketRequest: SocketResponse =
                GsonUtils.fromJson(text, SocketResponse::class.java)
            if (socketRequest.type == SocketType.LOGIN_SUCCESSFUL.desc) {
                isLoginSocket = true
                webSocket.send(text = mSendQueue.poll() ?: return)
            } else if (socketRequest.type == SocketType.SEND_SUCCESS.desc) {
                EventBus.getDefault().post(SocketType.SEND_SUCCESS)
            } else if (socketRequest.type == SocketType.RECEIVE.desc) {
                EventBus.getDefault().post(SocketType.RECEIVE)
            } else if (socketRequest.type == SocketType.SEND_FAILED.desc) {
                EventBus.getDefault().post(SocketType.SEND_FAILED)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }

        NetworkUtils.isAvailableByPingAsync { }
    }

    /**
     * 连接
     * */
    private fun connect(): WebSocket? {
        if (mWebSocket == null) mWebSocket =
            HttpServiceFactory.create(
                listener = this,
                wsUrl = mWsUrl
            )
        return mWebSocket
    }

    /**
     * 发送数据
     * */
    fun send(text: String) {
        if (mWebSocket == null)
            connect()
        if (isLoginSocket) {
            mWebSocket?.send(text)
        } else {
            mSendQueue.offer(text)
        }
    }

    /**
     * 取消连接
     * */
    fun cancel() {
        mWebSocket?.cancel()
    }

    /**
     * 关闭连接
     * */
    private fun close() {
        isLoginSocket = false
        mHandler.removeCallbacks(mRunnable)
        mWebSocket?.close(code = 1000, reason = null)
        mWebSocket = null
    }

    /**
     * 登录
     * */
    fun login() {
        val userId: Int = RZApplication.userInfoMe()?.id
            ?: return
        val token: String = RZApplication.token()
            ?: return
        val loginRequest =
            SocketLoginRequest(user_id = userId.toString(), token = token)
        if (!isLoginSocket) {
            mWebSocket?.send(GsonUtils.toJson(loginRequest))
        }
    }

    /**
     * ping
     * */
    private fun ping() {
        mHandler.postDelayed(mRunnable, DELAY_MILLIS)
    }

}